home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / base / netkit-b.07a / netkit-b / NetKit-B-0.07A / ftp / ftp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-21  |  33.8 KB  |  1,575 lines

  1. /*
  2.  * Copyright (c) 1985, 1989 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. /* 
  35.  * From: @(#)ftp.c    5.38 (Berkeley) 4/22/91
  36.  */
  37. char ftp_rcsid[] = 
  38.   "$Id: ftp.c,v 1.7 1996/07/21 09:28:33 dholland Exp $";
  39.  
  40.  
  41. #include <sys/param.h>
  42. #include <sys/stat.h>
  43. #include <sys/ioctl.h>
  44. #include <sys/socket.h>
  45. #include <sys/time.h>
  46. #include <sys/file.h>
  47.  
  48. #include <netinet/in.h>
  49. #include <netinet/ip.h>
  50. #include <arpa/ftp.h>
  51. #include <arpa/inet.h>
  52. #include <arpa/telnet.h>
  53.  
  54. #include <stdio.h>
  55. #include <signal.h>
  56. #include <string.h>
  57. #include <stdlib.h>
  58. #include <unistd.h>
  59. #include <errno.h>
  60. #include <netdb.h>
  61. #include <fcntl.h>
  62. #include <pwd.h>
  63. #include <stdarg.h>
  64.  
  65. #include "ftp_var.h"
  66.  
  67. struct    sockaddr_in hisctladdr;
  68. struct    sockaddr_in data_addr;
  69. int    data = -1;
  70. int    abrtflag = 0;
  71. int    ptflag = 0;
  72. struct    sockaddr_in myctladdr;
  73. uid_t    getuid();
  74. off_t    restart_point = 0;
  75.  
  76. void lostpeer(int);
  77. extern int connected;
  78.  
  79. static void proxtrans(char *cmd, char *local, char *remote);
  80. static int initconn(void);
  81. static void ptransfer(char *direction, long bytes, 
  82.               struct timeval *t0, struct timeval *t1);
  83. static void tvsub(struct timeval *tdiff, 
  84.           const struct timeval *t1, 
  85.           const struct timeval *t0);
  86. static void abort_remote(FILE *din);
  87.  
  88. FILE    *cin, *cout;
  89. FILE    *dataconn();
  90.  
  91. char *
  92. hookup(host, port)
  93.     char *host;
  94.     int port;
  95. {
  96.     register struct hostent *hp = 0;
  97.     int s, len, tos;
  98.     static char hostnamebuf[80];
  99.  
  100.     memset((char *)&hisctladdr, 0, sizeof(hisctladdr));
  101.     hisctladdr.sin_addr.s_addr = inet_addr(host);
  102.     if (hisctladdr.sin_addr.s_addr != -1) {
  103.         hisctladdr.sin_family = AF_INET;
  104.         (void) strncpy(hostnamebuf, host, sizeof(hostnamebuf));
  105.     } else {
  106.         hp = gethostbyname(host);
  107.         if (hp == NULL) {
  108.             fprintf(stderr, "ftp: %s: ", host);
  109.             herror((char *)NULL);
  110.             code = -1;
  111.             return((char *) 0);
  112.         }
  113.         hisctladdr.sin_family = hp->h_addrtype;
  114.         bcopy(hp->h_addr_list[0],
  115.             (caddr_t)&hisctladdr.sin_addr, hp->h_length);
  116.         (void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf));
  117.     }
  118.     hostname = hostnamebuf;
  119.     s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
  120.     if (s < 0) {
  121.         perror("ftp: socket");
  122.         code = -1;
  123.         return (0);
  124.     }
  125.     hisctladdr.sin_port = port;
  126.     while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) {
  127.         if (hp && hp->h_addr_list[1]) {
  128.             int oerrno = errno;
  129.             extern char *inet_ntoa();
  130.  
  131.             fprintf(stderr, "ftp: connect to address %s: ",
  132.                 inet_ntoa(hisctladdr.sin_addr));
  133.             errno = oerrno;
  134.             perror((char *) 0);
  135.             hp->h_addr_list++;
  136.             bcopy(hp->h_addr_list[0],
  137.                  (caddr_t)&hisctladdr.sin_addr, hp->h_length);
  138.             fprintf(stdout, "Trying %s...\n",
  139.                 inet_ntoa(hisctladdr.sin_addr));
  140.             (void) close(s);
  141.             s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
  142.             if (s < 0) {
  143.                 perror("ftp: socket");
  144.                 code = -1;
  145.                 return (0);
  146.             }
  147.             continue;
  148.         }
  149.         perror("ftp: connect");
  150.         code = -1;
  151.         goto bad;
  152.     }
  153.     len = sizeof (myctladdr);
  154.     if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) {
  155.         perror("ftp: getsockname");
  156.         code = -1;
  157.         goto bad;
  158.     }
  159. #ifdef IP_TOS
  160.     tos = IPTOS_LOWDELAY;
  161.     if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
  162.         perror("ftp: setsockopt TOS (ignored)");
  163. #endif
  164.     cin = fdopen(s, "r");
  165.     cout = fdopen(s, "w");
  166.     if (cin == NULL || cout == NULL) {
  167.         fprintf(stderr, "ftp: fdopen failed.\n");
  168.         if (cin)
  169.             (void) fclose(cin);
  170.         if (cout)
  171.             (void) fclose(cout);
  172.         code = -1;
  173.         goto bad;
  174.     }
  175.     if (verbose)
  176.         printf("Connected to %s.\n", hostname);
  177.     if (getreply(0) > 2) {     /* read startup message from server */
  178.         if (cin)
  179.             (void) fclose(cin);
  180.         if (cout)
  181.             (void) fclose(cout);
  182.         code = -1;
  183.         goto bad;
  184.     }
  185. #ifdef SO_OOBINLINE
  186.     {
  187.     int on = 1;
  188.  
  189.     if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on))
  190.         < 0 && debug) {
  191.             perror("ftp: setsockopt");
  192.         }
  193.     }
  194. #endif /* SO_OOBINLINE */
  195.  
  196.     return (hostname);
  197. bad:
  198.     (void) close(s);
  199.     return ((char *)0);
  200. }
  201.  
  202. int
  203. login(const char *host)
  204. {
  205.     char tmp[80];
  206.     char *user, *pass, *acct, *getlogin(), *getpass();
  207.     int n, aflag = 0;
  208.  
  209.     user = pass = acct = 0;
  210.     if (xruserpass(host, &user, &pass, &acct) < 0) {
  211.         code = -1;
  212.         return(0);
  213.     }
  214.     while (user == NULL) {
  215.         char *myname = getlogin();
  216.  
  217.         if (myname == NULL) {
  218.             struct passwd *pp = getpwuid(getuid());
  219.  
  220.             if (pp != NULL)
  221.                 myname = pp->pw_name;
  222.         }
  223.         if (myname)
  224.             printf("Name (%s:%s): ", host, myname);
  225.         else
  226.             printf("Name (%s): ", host);
  227.         (void) fgets(tmp, sizeof(tmp) - 1, stdin);
  228.         tmp[strlen(tmp) - 1] = '\0';
  229.         if (*tmp == '\0')
  230.             user = myname;
  231.         else
  232.             user = tmp;
  233.     }
  234.     n = command("USER %s", user);
  235.     if (n == CONTINUE) {
  236.         if (pass == NULL) {
  237.             /* fflush(stdout); */
  238.             pass = getpass("Password:");
  239.         }
  240.         n = command("PASS %s", pass);
  241.     }
  242.     if (n == CONTINUE) {
  243.         aflag++;
  244.         /* fflush(stdout); */
  245.         acct = getpass("Account:");
  246.         n = command("ACCT %s", acct);
  247.     }
  248.     if (n != COMPLETE) {
  249.         fprintf(stderr, "Login failed.\n");
  250.         return (0);
  251.     }
  252.     if (!aflag && acct != NULL)
  253.         (void) command("ACCT %s", acct);
  254.     if (proxy)
  255.         return(1);
  256.     for (n = 0; n < macnum; ++n) {
  257.         if (!strcmp("init", macros[n].mac_name)) {
  258.             (void) strcpy(line, "$init");
  259.             makeargv();
  260.             domacro(margc, margv);
  261.             break;
  262.         }
  263.     }
  264.     return (1);
  265. }
  266.  
  267. void
  268. cmdabort(int ignore)
  269. {
  270.     extern sigjmp_buf ptabort;
  271.  
  272.     printf("\n");
  273.     (void) fflush(stdout);
  274.     abrtflag++;
  275.     if (ptflag)
  276.         siglongjmp(ptabort,1);
  277. }
  278.  
  279. int
  280. command(const char *fmt, ...)
  281. {
  282.     va_list ap;
  283.     int r;
  284.     void (*oldintr)(int);
  285.  
  286.     abrtflag = 0;
  287.     if (debug) {
  288.         printf("---> ");
  289.         va_start(ap, fmt);
  290.         if (strncmp("PASS ", fmt, 5) == 0)
  291.             printf("PASS XXXX");
  292.         else 
  293.             vfprintf(stdout, fmt, ap);
  294.         va_end(ap);
  295.         printf("\n");
  296.         (void) fflush(stdout);
  297.     }
  298.     if (cout == NULL) {
  299.         perror ("No control connection for command");
  300.         code = -1;
  301.         return (0);
  302.     }
  303.     oldintr = signal(SIGINT, cmdabort);
  304.     va_start(ap, fmt);
  305.     vfprintf(cout, fmt, ap);
  306.     va_end(ap);
  307.     fprintf(cout, "\r\n");
  308.     (void) fflush(cout);
  309.     cpend = 1;
  310.     r = getreply(!strcmp(fmt, "QUIT"));
  311.     if (abrtflag && oldintr != SIG_IGN)
  312.         (*oldintr)(SIGINT);
  313.     (void) signal(SIGINT, oldintr);
  314.     return(r);
  315. }
  316.  
  317. char reply_string[BUFSIZ];        /* last line of previous reply */
  318.  
  319. #include <ctype.h>
  320.  
  321. int
  322. getreply(int expecteof)
  323. {
  324.     register int c, n;
  325.     register int dig;
  326.     register char *cp;
  327.     int originalcode = 0, continuation = 0;
  328.     void (*oldintr)(int);
  329.     int pflag = 0;
  330.     char *pt = pasv;
  331.  
  332.     oldintr = signal(SIGINT, cmdabort);
  333.     for (;;) {
  334.         dig = n = code = 0;
  335.         cp = reply_string;
  336.         while ((c = getc(cin)) != '\n') {
  337.             if (c == IAC) {     /* handle telnet commands */
  338.                 switch (c = getc(cin)) {
  339.                 case WILL:
  340.                 case WONT:
  341.                     c = getc(cin);
  342.                     fprintf(cout, "%c%c%c", IAC, DONT, c);
  343.                     (void) fflush(cout);
  344.                     break;
  345.                 case DO:
  346.                 case DONT:
  347.                     c = getc(cin);
  348.                     fprintf(cout, "%c%c%c", IAC, WONT, c);
  349.                     (void) fflush(cout);
  350.                     break;
  351.                 default:
  352.                     break;
  353.                 }
  354.                 continue;
  355.             }
  356.             dig++;
  357.             if (c == EOF) {
  358.                 if (expecteof) {
  359.                     (void) signal(SIGINT,oldintr);
  360.                     code = 221;
  361.                     return (0);
  362.                 }
  363.                 lostpeer(0);
  364.                 if (verbose) {
  365.                     printf("421 Service not available, remote server has closed connection\n");
  366.                     (void) fflush(stdout);
  367.                 }
  368.                 code = 421;
  369.                 return(4);
  370.             }
  371.             if (c != '\r' && (verbose > 0 ||
  372.                 (verbose > -1 && n == '5' && dig > 4))) {
  373.                 if (proxflag &&
  374.                    (dig == 1 || (dig == 5 && verbose == 0)))
  375.                     printf("%s:",hostname);
  376.                 (void) putchar(c);
  377.             }
  378.             if (dig < 4 && isdigit(c))
  379.                 code = code * 10 + (c - '0');
  380.             if (!pflag && code == 227)
  381.                 pflag = 1;
  382.             if (dig > 4 && pflag == 1 && isdigit(c))
  383.                 pflag = 2;
  384.             if (pflag == 2) {
  385.                 if (c != '\r' && c != ')')
  386.                     *pt++ = c;
  387.                 else {
  388.                     *pt = '\0';
  389.                     pflag = 3;
  390.                 }
  391.             }
  392.             if (dig == 4 && c == '-') {
  393.                 if (continuation)
  394.                     code = 0;
  395.                 continuation++;
  396.             }
  397.             if (n == 0)
  398.                 n = c;
  399.             if (cp < &reply_string[sizeof(reply_string) - 1])
  400.                 *cp++ = c;
  401.         }
  402.         if (verbose > 0 || (verbose > -1 && n == '5')) {
  403.             (void) putchar(c);
  404.             (void) fflush (stdout);
  405.         }
  406.         if (continuation && code != originalcode) {
  407.             if (originalcode == 0)
  408.                 originalcode = code;
  409.             continue;
  410.         }
  411.         *cp = '\0';
  412.         if (n != '1')
  413.             cpend = 0;
  414.         (void) signal(SIGINT,oldintr);
  415.         if (code == 421 || originalcode == 421)
  416.             lostpeer(0);
  417.         if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
  418.             (*oldintr)(SIGINT);
  419.         return (n - '0');
  420.     }
  421. }
  422.  
  423. int
  424. empty(fd_set *mask, int sec)
  425. {
  426.     struct timeval t;
  427.  
  428.     t.tv_sec = (long) sec;
  429.     t.tv_usec = 0;
  430.     return(select(32, mask, (fd_set *) 0, (fd_set *) 0, &t));
  431. }
  432.  
  433. sigjmp_buf    sendabort;
  434.  
  435. void
  436. abortsend(int ignore)
  437. {
  438.  
  439.     mflag = 0;
  440.     abrtflag = 0;
  441.     printf("\nsend aborted\nwaiting for remote to finish abort\n");
  442.     (void) fflush(stdout);
  443.     siglongjmp(sendabort, 1);
  444. }
  445.  
  446. #define HASHBYTES 1024
  447.  
  448. void
  449. sendrequest(char *cmd, char *local, char *remote, int printnames)
  450. {
  451.     struct stat st;
  452.     struct timeval start, stop;
  453.     register int c, d;
  454.     FILE *volatile fin, *volatile dout = 0;
  455.     int (*volatile closefunc)();
  456.     void (*volatile oldintr)(int);
  457.     void (*volatile oldintp)(int);
  458.     volatile long bytes = 0, hashbytes = HASHBYTES;
  459.     char *volatile lmode, buf[BUFSIZ], *bufp;
  460.  
  461.     if (verbose && printnames) {
  462.         if (local && *local != '-')
  463.             printf("local: %s ", local);
  464.         if (remote)
  465.             printf("remote: %s\n", remote);
  466.     }
  467.     if (proxy) {
  468.         proxtrans(cmd, local, remote);
  469.         return;
  470.     }
  471.     if (curtype != type)
  472.         changetype(type, 0);
  473.     closefunc = NULL;
  474.     oldintr = NULL;
  475.     oldintp = NULL;
  476.     lmode = "w";
  477.     if (sigsetjmp(sendabort, 1)) {
  478.         while (cpend) {
  479.             (void) getreply(0);
  480.         }
  481.         if (data >= 0) {
  482.             (void) close(data);
  483.             data = -1;
  484.         }
  485.         if (oldintr)
  486.             (void) signal(SIGINT,oldintr);
  487.         if (oldintp)
  488.             (void) signal(SIGPIPE,oldintp);
  489.         code = -1;
  490.         return;
  491.     }
  492.     oldintr = signal(SIGINT, abortsend);
  493.     if (strcmp(local, "-") == 0)
  494.         fin = stdin;
  495.     else if (*local == '|') {
  496.         oldintp = signal(SIGPIPE,SIG_IGN);
  497.         fin = popen(local + 1, "r");
  498.         if (fin == NULL) {
  499.             perror(local + 1);
  500.             (void) signal(SIGINT, oldintr);
  501.             (void) signal(SIGPIPE, oldintp);
  502.             code = -1;
  503.             return;
  504.         }
  505.         closefunc = pclose;
  506.     } else {
  507.         fin = fopen(local, "r");
  508.         if (fin == NULL) {
  509.             fprintf(stderr, "local: %s: %s\n", local,
  510.                 strerror(errno));
  511.             (void) signal(SIGINT, oldintr);
  512.             code = -1;
  513.             return;
  514.         }
  515.         closefunc = fclose;
  516.         if (fstat(fileno(fin), &st) < 0 ||
  517.             (st.st_mode&S_IFMT) != S_IFREG) {
  518.             fprintf(stdout, "%s: not a plain file.\n", local);
  519.             (void) signal(SIGINT, oldintr);
  520.             fclose(fin);
  521.             code = -1;
  522.             return;
  523.         }
  524.     }
  525.     if (initconn()) {
  526.         (void) signal(SIGINT, oldintr);
  527.         if (oldintp)
  528.             (void) signal(SIGPIPE, oldintp);
  529.         code = -1;
  530.         if (closefunc != NULL)
  531.             (*closefunc)(fin);
  532.         return;
  533.     }
  534.     if (sigsetjmp(sendabort, 1))
  535.         goto abort;
  536.  
  537.     if (restart_point &&
  538.         (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
  539.         if (fseek(fin, (long) restart_point, 0) < 0) {
  540.             fprintf(stderr, "local: %s: %s\n", local,
  541.                 strerror(errno));
  542.             restart_point = 0;
  543.             if (closefunc != NULL)
  544.                 (*closefunc)(fin);
  545.             return;
  546.         }
  547.         if (command("REST %ld", (long) restart_point)
  548.             != CONTINUE) {
  549.             restart_point = 0;
  550.             if (closefunc != NULL)
  551.                 (*closefunc)(fin);
  552.             return;
  553.         }
  554.         restart_point = 0;
  555.         lmode = "r+w";
  556.     }
  557.     if (remote) {
  558.         if (command("%s %s", cmd, remote) != PRELIM) {
  559.             (void) signal(SIGINT, oldintr);
  560.             if (oldintp)
  561.                 (void) signal(SIGPIPE, oldintp);
  562.             if (closefunc != NULL)
  563.                 (*closefunc)(fin);
  564.             return;
  565.         }
  566.     } else
  567.         if (command("%s", cmd) != PRELIM) {
  568.             (void) signal(SIGINT, oldintr);
  569.             if (oldintp)
  570.                 (void) signal(SIGPIPE, oldintp);
  571.             if (closefunc != NULL)
  572.                 (*closefunc)(fin);
  573.             return;
  574.         }
  575.     dout = dataconn(lmode);
  576.     if (dout == NULL)
  577.         goto abort;
  578.     (void) gettimeofday(&start, (struct timezone *)0);
  579.     oldintp = signal(SIGPIPE, SIG_IGN);
  580.     switch (curtype) {
  581.  
  582.     case TYPE_I:
  583.     case TYPE_L:
  584.         errno = d = 0;
  585.         while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) {
  586.             bytes += c;
  587.             for (bufp = buf; c > 0; c -= d, bufp += d)
  588.                 if ((d = write(fileno(dout), bufp, c)) <= 0)
  589.                     break;
  590.             if (hash) {
  591.                 while (bytes >= hashbytes) {
  592.                     (void) putchar('#');
  593.                     hashbytes += HASHBYTES;
  594.                 }
  595.                 (void) fflush(stdout);
  596.             }
  597.             if (tick && (bytes >= hashbytes)) {
  598.                 printf("\rBytes transferred: %ld", bytes);
  599.                 (void) fflush(stdout);
  600.                 while (bytes >= hashbytes)
  601.                     hashbytes += TICKBYTES;
  602.             }
  603.         }
  604.         if (hash && (bytes > 0)) {
  605.             if (bytes < HASHBYTES)
  606.                 (void) putchar('#');
  607.             (void) putchar('\n');
  608.             (void) fflush(stdout);
  609.         }
  610.         if (tick) {
  611.             (void) printf("\rBytes transferred: %ld\n", bytes);
  612.             (void) fflush(stdout);
  613.         }
  614.         if (c < 0)
  615.             fprintf(stderr, "local: %s: %s\n", local,
  616.                 strerror(errno));
  617.         if (d < 0) {
  618.             if (errno != EPIPE) 
  619.                 perror("netout");
  620.             bytes = -1;
  621.         }
  622.         break;
  623.  
  624.     case TYPE_A:
  625.         while ((c = getc(fin)) != EOF) {
  626.             if (c == '\n') {
  627.                 while (hash && (bytes >= hashbytes)) {
  628.                     (void) putchar('#');
  629.                     (void) fflush(stdout);
  630.                     hashbytes += HASHBYTES;
  631.                 }
  632.                 if (tick && (bytes >= hashbytes)) {
  633.                     (void) printf("\rBytes transferred: %ld",
  634.                         bytes);
  635.                     (void) fflush(stdout);
  636.                     while (bytes >= hashbytes)
  637.                         hashbytes += TICKBYTES;
  638.                 }
  639.                 if (ferror(dout))
  640.                     break;
  641.                 (void) putc('\r', dout);
  642.                 bytes++;
  643.             }
  644.             (void) putc(c, dout);
  645.             bytes++;
  646.     /*        if (c == '\r') {                  */
  647.     /*        (void)    putc('\0', dout);  (* this violates rfc */
  648.     /*            bytes++;                */
  649.     /*        }                                      */     
  650.         }
  651.         if (hash) {
  652.             if (bytes < hashbytes)
  653.                 (void) putchar('#');
  654.             (void) putchar('\n');
  655.             (void) fflush(stdout);
  656.         }
  657.         if (tick) {
  658.             (void) printf("\rBytes transferred: %ld\n", bytes);
  659.             (void) fflush(stdout);
  660.         }
  661.         if (ferror(fin))
  662.             fprintf(stderr, "local: %s: %s\n", local,
  663.                 strerror(errno));
  664.         if (ferror(dout)) {
  665.             if (errno != EPIPE)
  666.                 perror("netout");
  667.             bytes = -1;
  668.         }
  669.         break;
  670.     }
  671.     (void) gettimeofday(&stop, (struct timezone *)0);
  672.     if (closefunc != NULL)
  673.         (*closefunc)(fin);
  674.     (void) fclose(dout);
  675.     (void) getreply(0);
  676.     (void) signal(SIGINT, oldintr);
  677.     if (oldintp)
  678.         (void) signal(SIGPIPE, oldintp);
  679.     if (bytes > 0)
  680.         ptransfer("sent", bytes, &start, &stop);
  681.     return;
  682. abort:
  683.     (void) gettimeofday(&stop, (struct timezone *)0);
  684.     (void) signal(SIGINT, oldintr);
  685.     if (oldintp)
  686.         (void) signal(SIGPIPE, oldintp);
  687.     if (!cpend) {
  688.         code = -1;
  689.         return;
  690.     }
  691.     if (data >= 0) {
  692.         (void) close(data);
  693.         data = -1;
  694.     }
  695.     if (dout)
  696.         (void) fclose(dout);
  697.     (void) getreply(0);
  698.     code = -1;
  699.     if (closefunc != NULL && fin != NULL)
  700.         (*closefunc)(fin);
  701.     if (bytes > 0)
  702.         ptransfer("sent", bytes, &start, &stop);
  703. }
  704.  
  705. sigjmp_buf    recvabort;
  706.  
  707. void
  708. abortrecv(int ignore)
  709. {
  710.  
  711.     mflag = 0;
  712.     abrtflag = 0;
  713.     printf("\nreceive aborted\nwaiting for remote to finish abort\n");
  714.     (void) fflush(stdout);
  715.     siglongjmp(recvabort, 1);
  716. }
  717.  
  718. void
  719. recvrequest(char *cmd, char *volatile local, char *remote, char *lmode, int printnames)
  720. {
  721.     FILE *volatile fout, *volatile din = 0;
  722.     int (*volatile closefunc)();
  723.     void (*volatile oldintp)(int);
  724.     void (*volatile oldintr)(int);
  725.     volatile int is_retr, tcrflag, bare_lfs = 0;
  726.     char *gunique();
  727.     static int bufsize;
  728.     static char *buf;
  729.     volatile long bytes = 0, hashbytes = HASHBYTES;
  730.     register int c, d;
  731.     struct timeval start, stop;
  732.     struct stat st;
  733.  
  734.     is_retr = strcmp(cmd, "RETR") == 0;
  735.     if (is_retr && verbose && printnames) {
  736.         if (local && *local != '-')
  737.             printf("local: %s ", local);
  738.         if (remote)
  739.             printf("remote: %s\n", remote);
  740.     }
  741.     if (proxy && is_retr) {
  742.         proxtrans(cmd, local, remote);
  743.         return;
  744.     }
  745.     closefunc = NULL;
  746.     oldintr = NULL;
  747.     oldintp = NULL;
  748.     tcrflag = !crflag && is_retr;
  749.     if (sigsetjmp(recvabort, 1)) {
  750.         while (cpend) {
  751.             (void) getreply(0);
  752.         }
  753.         if (data >= 0) {
  754.             (void) close(data);
  755.             data = -1;
  756.         }
  757.         if (oldintr)
  758.             (void) signal(SIGINT, oldintr);
  759.         code = -1;
  760.         return;
  761.     }
  762.     oldintr = signal(SIGINT, abortrecv);
  763.     if (strcmp(local, "-") && *local != '|') {
  764.         if (access(local, 2) < 0) {
  765.             char *dir = rindex(local, '/');
  766.  
  767.             if (errno != ENOENT && errno != EACCES) {
  768.                 fprintf(stderr, "local: %s: %s\n", local,
  769.                     strerror(errno));
  770.                 (void) signal(SIGINT, oldintr);
  771.                 code = -1;
  772.                 return;
  773.             }
  774.             if (dir != NULL)
  775.                 *dir = 0;
  776.             d = access(dir ? local : ".", 2);
  777.             if (dir != NULL)
  778.                 *dir = '/';
  779.             if (d < 0) {
  780.                 fprintf(stderr, "local: %s: %s\n", local,
  781.                     strerror(errno));
  782.                 (void) signal(SIGINT, oldintr);
  783.                 code = -1;
  784.                 return;
  785.             }
  786.             if (!runique && errno == EACCES &&
  787.                 chmod(local, 0600) < 0) {
  788.                 fprintf(stderr, "local: %s: %s\n", local,
  789.                     strerror(errno));
  790.                 (void) signal(SIGINT, oldintr);
  791.                 (void) signal(SIGINT, oldintr);
  792.                 code = -1;
  793.                 return;
  794.             }
  795.             if (runique && errno == EACCES &&
  796.                (local = gunique(local)) == NULL) {
  797.                 (void) signal(SIGINT, oldintr);
  798.                 code = -1;
  799.                 return;
  800.             }
  801.         }
  802.         else if (runique && (local = gunique(local)) == NULL) {
  803.             (void) signal(SIGINT, oldintr);
  804.             code = -1;
  805.             return;
  806.         }
  807.     }
  808.     if (!is_retr) {
  809.         if (curtype != TYPE_A)
  810.             changetype(TYPE_A, 0);
  811.     } else if (curtype != type)
  812.         changetype(type, 0);
  813.     if (initconn()) {
  814.         (void) signal(SIGINT, oldintr);
  815.         code = -1;
  816.         return;
  817.     }
  818.     if (sigsetjmp(recvabort, 1))
  819.         goto abort;
  820.     if (is_retr && restart_point &&
  821.         command("REST %ld", (long) restart_point) != CONTINUE)
  822.         return;
  823.     if (remote) {
  824.         if (command("%s %s", cmd, remote) != PRELIM) {
  825.             (void) signal(SIGINT, oldintr);
  826.             return;
  827.         }
  828.     } else {
  829.         if (command("%s", cmd) != PRELIM) {
  830.             (void) signal(SIGINT, oldintr);
  831.             return;
  832.         }
  833.     }
  834.     din = dataconn("r");
  835.     if (din == NULL)
  836.         goto abort;
  837.     if (strcmp(local, "-") == 0)
  838.         fout = stdout;
  839.     else if (*local == '|') {
  840.         oldintp = signal(SIGPIPE, SIG_IGN);
  841.         fout = popen(local + 1, "w");
  842.         if (fout == NULL) {
  843.             perror(local+1);
  844.             goto abort;
  845.         }
  846.         closefunc = pclose;
  847.     } else {
  848.         fout = fopen(local, lmode);
  849.         if (fout == NULL) {
  850.             fprintf(stderr, "local: %s: %s\n", local,
  851.                 strerror(errno));
  852.             goto abort;
  853.         }
  854.         closefunc = fclose;
  855.     }
  856.     if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0)
  857.         st.st_blksize = BUFSIZ;
  858.     if (st.st_blksize > bufsize) {
  859.         if (buf)
  860.             (void) free(buf);
  861.         buf = malloc((unsigned)st.st_blksize);
  862.         if (buf == NULL) {
  863.             perror("malloc");
  864.             bufsize = 0;
  865.             goto abort;
  866.         }
  867.         bufsize = st.st_blksize;
  868.     }
  869.     (void) gettimeofday(&start, (struct timezone *)0);
  870.     switch (curtype) {
  871.  
  872.     case TYPE_I:
  873.     case TYPE_L:
  874.         if (restart_point &&
  875.             lseek(fileno(fout), (long) restart_point, L_SET) < 0) {
  876.             fprintf(stderr, "local: %s: %s\n", local,
  877.                 strerror(errno));
  878.             if (closefunc != NULL)
  879.                 (*closefunc)(fout);
  880.             return;
  881.         }
  882.         errno = d = 0;
  883.         while ((c = read(fileno(din), buf, bufsize)) > 0) {
  884.             if ((d = write(fileno(fout), buf, c)) != c)
  885.                 break;
  886.             bytes += c;
  887.             if (hash && is_retr) {
  888.                 while (bytes >= hashbytes) {
  889.                     (void) putchar('#');
  890.                     hashbytes += HASHBYTES;
  891.                 }
  892.                 (void) fflush(stdout);
  893.             }
  894.             if (tick && (bytes >= hashbytes) && is_retr) {
  895.                 (void) printf("\rBytes transferred: %ld",
  896.                     bytes);
  897.                 (void) fflush(stdout);
  898.                 while (bytes >= hashbytes)
  899.                     hashbytes += TICKBYTES;
  900.             }
  901.         }
  902.         if (hash && bytes > 0) {
  903.             if (bytes < HASHBYTES)
  904.                 (void) putchar('#');
  905.             (void) putchar('\n');
  906.             (void) fflush(stdout);
  907.         }
  908.         if (tick && is_retr) {
  909.             (void) printf("\rBytes transferred: %ld\n", bytes);
  910.             (void) fflush(stdout);
  911.         }
  912.         if (c < 0) {
  913.             if (errno != EPIPE)
  914.                 perror("netin");
  915.             bytes = -1;
  916.         }
  917.         if (d < c) {
  918.             if (d < 0)
  919.                 fprintf(stderr, "local: %s: %s\n", local,
  920.                     strerror(errno));
  921.             else
  922.                 fprintf(stderr, "%s: short write\n", local);
  923.         }
  924.         break;
  925.  
  926.     case TYPE_A:
  927.         if (restart_point) {
  928.             register int i, n, ch;
  929.  
  930.             if (fseek(fout, 0L, L_SET) < 0)
  931.                 goto done;
  932.             n = restart_point;
  933.             for (i = 0; i++ < n;) {
  934.                 if ((ch = getc(fout)) == EOF)
  935.                     goto done;
  936.                 if (ch == '\n')
  937.                     i++;
  938.             }
  939.             if (fseek(fout, 0L, L_INCR) < 0) {
  940. done:
  941.                 fprintf(stderr, "local: %s: %s\n", local,
  942.                     strerror(errno));
  943.                 if (closefunc != NULL)
  944.                     (*closefunc)(fout);
  945.                 return;
  946.             }
  947.         }
  948.         while ((c = getc(din)) != EOF) {
  949.             if (c == '\n')
  950.                 bare_lfs++;
  951.             while (c == '\r') {
  952.                 while (hash && (bytes >= hashbytes)
  953.                     && is_retr) {
  954.                     (void) putchar('#');
  955.                     (void) fflush(stdout);
  956.                     hashbytes += HASHBYTES;
  957.                 }
  958.                 if (tick && (bytes >= hashbytes) && is_retr) {
  959.                     printf("\rBytes transferred: %ld",
  960.                         bytes);
  961.                     fflush(stdout);
  962.                     while (bytes >= hashbytes)
  963.                         hashbytes += TICKBYTES;
  964.                 }
  965.                 bytes++;
  966.                 if ((c = getc(din)) != '\n' || tcrflag) {
  967.                     if (ferror(fout))
  968.                         goto break2;
  969.                     (void) putc('\r', fout);
  970.                     if (c == '\0') {
  971.                         bytes++;
  972.                         goto contin2;
  973.                     }
  974.                     if (c == EOF)
  975.                         goto contin2;
  976.                 }
  977.             }
  978.             (void) putc(c, fout);
  979.             bytes++;
  980.     contin2:    ;
  981.         }
  982. break2:
  983.         if (hash && is_retr) {
  984.             if (bytes < hashbytes)
  985.                 (void) putchar('#');
  986.             (void) putchar('\n');
  987.             (void) fflush(stdout);
  988.         }
  989.         if (tick && is_retr) {
  990.             (void) printf("\rBytes transferred: %ld\n", bytes);
  991.             (void) fflush(stdout);
  992.         }
  993.         if (bare_lfs) {
  994.             printf("WARNING! %d bare linefeeds received in ASCII mode\n", bare_lfs);
  995.             printf("File may not have transferred correctly.\n");
  996.         }
  997.         if (ferror(din)) {
  998.             if (errno != EPIPE)
  999.                 perror("netin");
  1000.             bytes = -1;
  1001.         }
  1002.         if (ferror(fout))
  1003.             fprintf(stderr, "local: %s: %s\n", local,
  1004.                 strerror(errno));
  1005.         break;
  1006.     }
  1007.     if (closefunc != NULL)
  1008.         (*closefunc)(fout);
  1009.     (void) signal(SIGINT, oldintr);
  1010.     if (oldintp)
  1011.         (void) signal(SIGPIPE, oldintp);
  1012.     (void) gettimeofday(&stop, (struct timezone *)0);
  1013.     (void) fclose(din);
  1014.     (void) getreply(0);
  1015.     if (bytes > 0 && is_retr)
  1016.         ptransfer("received", bytes, &start, &stop);
  1017.     return;
  1018. abort:
  1019.  
  1020. /* abort using RFC959 recommended IP,SYNC sequence  */
  1021.  
  1022.     (void) gettimeofday(&stop, (struct timezone *)0);
  1023.     if (oldintp)
  1024.         (void) signal(SIGPIPE, oldintr);
  1025.     (void) signal(SIGINT, SIG_IGN);
  1026.     if (!cpend) {
  1027.         code = -1;
  1028.         (void) signal(SIGINT, oldintr);
  1029.         return;
  1030.     }
  1031.  
  1032.     abort_remote(din);
  1033.     code = -1;
  1034.     if (data >= 0) {
  1035.         (void) close(data);
  1036.         data = -1;
  1037.     }
  1038.     if (closefunc != NULL && fout != NULL)
  1039.         (*closefunc)(fout);
  1040.     if (din)
  1041.         (void) fclose(din);
  1042.     if (bytes > 0)
  1043.         ptransfer("received", bytes, &start, &stop);
  1044.     (void) signal(SIGINT, oldintr);
  1045. }
  1046.  
  1047. /*
  1048.  * Need to start a listen on the data channel before we send the command,
  1049.  * otherwise the server's connect may fail.
  1050.  */
  1051. static int
  1052. initconn(void)
  1053. {
  1054.     register char *p, *a;
  1055.     int result, len, tmpno = 0;
  1056.     int on = 1;
  1057.     int tos;
  1058.     u_long a1,a2,a3,a4,p1,p2;
  1059.  
  1060.     if (passivemode) {
  1061.         data = socket(AF_INET, SOCK_STREAM, 0);
  1062.         if (data < 0) {
  1063.             perror("ftp: socket");
  1064.             return(1);
  1065.         }
  1066.         if (options & SO_DEBUG &&
  1067.             setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on,
  1068.                    sizeof (on)) < 0)
  1069.             perror("ftp: setsockopt (ignored)");
  1070.         if (command("PASV") != COMPLETE) {
  1071.             printf("Passive mode refused.\n");
  1072.             return(1);
  1073.         }
  1074.  
  1075.         /*
  1076.          * What we've got at this point is a string of comma separated
  1077.          * one-byte unsigned integer values, separated by commas.
  1078.          * The first four are the an IP address. The fifth is the MSB
  1079.          * of the port number, the sixth is the LSB. From that we'll
  1080.          * prepare a sockaddr_in.
  1081.          */
  1082.  
  1083.         if (sscanf(pasv,"%ld,%ld,%ld,%ld,%ld,%ld",
  1084.                &a1,&a2,&a3,&a4,&p1,&p2)
  1085.             != 6) 
  1086.         {
  1087.             printf("Passive mode address scan failure. Shouldn't happen!\n");
  1088.             return(1);
  1089.         }
  1090.  
  1091.         data_addr.sin_family = AF_INET;
  1092.         data_addr.sin_addr.s_addr = htonl((a1 << 24) | (a2 << 16) |
  1093.                           (a3 << 8) | a4);
  1094.         data_addr.sin_port = htons((p1 << 8) | p2);
  1095.  
  1096.         if (connect(data, (struct sockaddr *) &data_addr,
  1097.             sizeof(data_addr))<0) {
  1098.             perror("ftp: connect");
  1099.             return(1);
  1100.         }
  1101. #ifdef IP_TOS
  1102.         tos = IPTOS_THROUGHPUT;
  1103.         if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&tos,
  1104.             sizeof(tos)) < 0)
  1105.             perror("ftp: setsockopt TOS (ignored)");
  1106. #endif
  1107.         return(0);
  1108.     }
  1109. noport:
  1110.     data_addr = myctladdr;
  1111.     if (sendport)
  1112.         data_addr.sin_port = 0;    /* let system pick one */ 
  1113.     if (data != -1)
  1114.         (void) close(data);
  1115.     data = socket(AF_INET, SOCK_STREAM, 0);
  1116.     if (data < 0) {
  1117.         perror("ftp: socket");
  1118.         if (tmpno)
  1119.             sendport = 1;
  1120.         return (1);
  1121.     }
  1122.     if (!sendport)
  1123.         if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) {
  1124.             perror("ftp: setsockopt (reuse address)");
  1125.             goto bad;
  1126.         }
  1127.     if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) {
  1128.         perror("ftp: bind");
  1129.         goto bad;
  1130.     }
  1131.     if (options & SO_DEBUG &&
  1132.         setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0)
  1133.         perror("ftp: setsockopt (ignored)");
  1134.     len = sizeof (data_addr);
  1135.     if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) {
  1136.         perror("ftp: getsockname");
  1137.         goto bad;
  1138.     }
  1139.     if (listen(data, 1) < 0)
  1140.         perror("ftp: listen");
  1141.     if (sendport) {
  1142.         a = (char *)&data_addr.sin_addr;
  1143.         p = (char *)&data_addr.sin_port;
  1144. #define    UC(b)    (((int)b)&0xff)
  1145.         result =
  1146.             command("PORT %d,%d,%d,%d,%d,%d",
  1147.               UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
  1148.               UC(p[0]), UC(p[1]));
  1149.         if (result == ERROR && sendport == -1) {
  1150.             sendport = 0;
  1151.             tmpno = 1;
  1152.             goto noport;
  1153.         }
  1154.         return (result != COMPLETE);
  1155.     }
  1156.     if (tmpno)
  1157.         sendport = 1;
  1158. #ifdef IP_TOS
  1159.     on = IPTOS_THROUGHPUT;
  1160.     if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
  1161.         perror("ftp: setsockopt TOS (ignored)");
  1162. #endif
  1163.     return (0);
  1164. bad:
  1165.     (void) close(data), data = -1;
  1166.     if (tmpno)
  1167.         sendport = 1;
  1168.     return (1);
  1169. }
  1170.  
  1171. FILE *
  1172. dataconn(lmode)
  1173.     char *lmode;
  1174. {
  1175.     struct sockaddr_in from;
  1176.     int s, fromlen = sizeof (from), tos;
  1177.  
  1178.         if (passivemode)
  1179.             return (fdopen(data, lmode));
  1180.  
  1181.     s = accept(data, (struct sockaddr *) &from, &fromlen);
  1182.     if (s < 0) {
  1183.         perror("ftp: accept");
  1184.         (void) close(data), data = -1;
  1185.         return (NULL);
  1186.     }
  1187.     (void) close(data);
  1188.     data = s;
  1189. #ifdef IP_TOS
  1190.     tos = IPTOS_THROUGHPUT;
  1191.     if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
  1192.         perror("ftp: setsockopt TOS (ignored)");
  1193. #endif
  1194.     return (fdopen(data, lmode));
  1195. }
  1196.  
  1197. static void
  1198. ptransfer(char *direction, long bytes, struct timeval *t0, struct timeval *t1)
  1199. {
  1200.     struct timeval td;
  1201.     float s, bs;
  1202.  
  1203.     if (verbose) {
  1204.         tvsub(&td, t1, t0);
  1205.         s = td.tv_sec + (td.tv_usec / 1000000.);
  1206. #define    nz(x)    ((x) == 0 ? 1 : (x))
  1207.         bs = bytes / nz(s);
  1208.         printf("%ld bytes %s in %.3g secs (%.2g Kbytes/sec)\n",
  1209.             bytes, direction, s, bs / 1024.0);
  1210.     }
  1211. }
  1212.  
  1213. #if 0
  1214. tvadd(tsum, t0)
  1215.     struct timeval *tsum, *t0;
  1216. {
  1217.  
  1218.     tsum->tv_sec += t0->tv_sec;
  1219.     tsum->tv_usec += t0->tv_usec;
  1220.     if (tsum->tv_usec > 1000000)
  1221.         tsum->tv_sec++, tsum->tv_usec -= 1000000;
  1222. }
  1223. #endif
  1224.  
  1225. static void
  1226. tvsub(struct timeval *tdiff, 
  1227.       const struct timeval *t1, 
  1228.       const struct timeval *t0)
  1229. {
  1230.  
  1231.     tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
  1232.     tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
  1233.     if (tdiff->tv_usec < 0)
  1234.         tdiff->tv_sec--, tdiff->tv_usec += 1000000;
  1235. }
  1236.  
  1237. void
  1238. psabort(int ignore)
  1239. {
  1240.     extern int abrtflag;
  1241.  
  1242.     abrtflag++;
  1243. }
  1244.  
  1245. void
  1246. pswitch(int flag)
  1247. {
  1248.     extern int proxy, abrtflag;
  1249.     void (*oldintr)(int);
  1250.     static struct comvars {
  1251.         int connect;
  1252.         char name[MAXHOSTNAMELEN];
  1253.         struct sockaddr_in mctl;
  1254.         struct sockaddr_in hctl;
  1255.         FILE *in;
  1256.         FILE *out;
  1257.         int tpe;
  1258.         int curtpe;
  1259.         int cpnd;
  1260.         int sunqe;
  1261.         int runqe;
  1262.         int mcse;
  1263.         int ntflg;
  1264.         char nti[17];
  1265.         char nto[17];
  1266.         int mapflg;
  1267.         char mi[MAXPATHLEN];
  1268.         char mo[MAXPATHLEN];
  1269.     } proxstruct, tmpstruct;
  1270.     struct comvars *ip, *op;
  1271.  
  1272.     abrtflag = 0;
  1273.     oldintr = signal(SIGINT, psabort);
  1274.     if (flag) {
  1275.         if (proxy)
  1276.             return;
  1277.         ip = &tmpstruct;
  1278.         op = &proxstruct;
  1279.         proxy++;
  1280.     } else {
  1281.         if (!proxy)
  1282.             return;
  1283.         ip = &proxstruct;
  1284.         op = &tmpstruct;
  1285.         proxy = 0;
  1286.     }
  1287.     ip->connect = connected;
  1288.     connected = op->connect;
  1289.     if (hostname) {
  1290.         (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1);
  1291.         ip->name[strlen(ip->name)] = '\0';
  1292.     } else
  1293.         ip->name[0] = 0;
  1294.     hostname = op->name;
  1295.     ip->hctl = hisctladdr;
  1296.     hisctladdr = op->hctl;
  1297.     ip->mctl = myctladdr;
  1298.     myctladdr = op->mctl;
  1299.     ip->in = cin;
  1300.     cin = op->in;
  1301.     ip->out = cout;
  1302.     cout = op->out;
  1303.     ip->tpe = type;
  1304.     type = op->tpe;
  1305.     ip->curtpe = curtype;
  1306.     curtype = op->curtpe;
  1307.     ip->cpnd = cpend;
  1308.     cpend = op->cpnd;
  1309.     ip->sunqe = sunique;
  1310.     sunique = op->sunqe;
  1311.     ip->runqe = runique;
  1312.     runique = op->runqe;
  1313.     ip->mcse = mcase;
  1314.     mcase = op->mcse;
  1315.     ip->ntflg = ntflag;
  1316.     ntflag = op->ntflg;
  1317.     (void) strncpy(ip->nti, ntin, 16);
  1318.     (ip->nti)[strlen(ip->nti)] = '\0';
  1319.     (void) strcpy(ntin, op->nti);
  1320.     (void) strncpy(ip->nto, ntout, 16);
  1321.     (ip->nto)[strlen(ip->nto)] = '\0';
  1322.     (void) strcpy(ntout, op->nto);
  1323.     ip->mapflg = mapflag;
  1324.     mapflag = op->mapflg;
  1325.     (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1);
  1326.     (ip->mi)[strlen(ip->mi)] = '\0';
  1327.     (void) strcpy(mapin, op->mi);
  1328.     (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1);
  1329.     (ip->mo)[strlen(ip->mo)] = '\0';
  1330.     (void) strcpy(mapout, op->mo);
  1331.     (void) signal(SIGINT, oldintr);
  1332.     if (abrtflag) {
  1333.         abrtflag = 0;
  1334.         (*oldintr)(SIGINT);
  1335.     }
  1336. }
  1337.  
  1338. sigjmp_buf ptabort;
  1339. int ptabflg;
  1340.  
  1341. void
  1342. abortpt(int ignore)
  1343. {
  1344.     printf("\n");
  1345.     (void) fflush(stdout);
  1346.     ptabflg++;
  1347.     mflag = 0;
  1348.     abrtflag = 0;
  1349.     siglongjmp(ptabort, 1);
  1350. }
  1351.  
  1352. static void
  1353. proxtrans(char *cmd, char *local, char *remote)
  1354. {
  1355.     void (*volatile oldintr)(int);
  1356.     volatile int secndflag = 0, prox_type, nfnd;
  1357.     extern sigjmp_buf ptabort;
  1358.     char *volatile cmd2;
  1359.     fd_set mask;
  1360.  
  1361.     if (strcmp(cmd, "RETR"))
  1362.         cmd2 = "RETR";
  1363.     else
  1364.         cmd2 = runique ? "STOU" : "STOR";
  1365.     if ((prox_type = type) == 0) {
  1366.         if (unix_server && unix_proxy)
  1367.             prox_type = TYPE_I;
  1368.         else
  1369.             prox_type = TYPE_A;
  1370.     }
  1371.     if (curtype != prox_type)
  1372.         changetype(prox_type, 1);
  1373.     if (command("PASV") != COMPLETE) {
  1374.         printf("proxy server does not support third party transfers.\n");
  1375.         return;
  1376.     }
  1377.     pswitch(0);
  1378.     if (!connected) {
  1379.         printf("No primary connection\n");
  1380.         pswitch(1);
  1381.         code = -1;
  1382.         return;
  1383.     }
  1384.     if (curtype != prox_type)
  1385.         changetype(prox_type, 1);
  1386.     if (command("PORT %s", pasv) != COMPLETE) {
  1387.         pswitch(1);
  1388.         return;
  1389.     }
  1390.     if (sigsetjmp(ptabort, 1))
  1391.         goto abort;
  1392.     oldintr = signal(SIGINT, abortpt);
  1393.     if (command("%s %s", cmd, remote) != PRELIM) {
  1394.         (void) signal(SIGINT, oldintr);
  1395.         pswitch(1);
  1396.         return;
  1397.     }
  1398.     sleep(2);
  1399.     pswitch(1);
  1400.     secndflag++;
  1401.     if (command("%s %s", cmd2, local) != PRELIM)
  1402.         goto abort;
  1403.     ptflag++;
  1404.     (void) getreply(0);
  1405.     pswitch(0);
  1406.     (void) getreply(0);
  1407.     (void) signal(SIGINT, oldintr);
  1408.     pswitch(1);
  1409.     ptflag = 0;
  1410.     printf("local: %s remote: %s\n", local, remote);
  1411.     return;
  1412. abort:
  1413.     (void) signal(SIGINT, SIG_IGN);
  1414.     ptflag = 0;
  1415.     if (strcmp(cmd, "RETR") && !proxy)
  1416.         pswitch(1);
  1417.     else if (!strcmp(cmd, "RETR") && proxy)
  1418.         pswitch(0);
  1419.     if (!cpend && !secndflag) {  /* only here if cmd = "STOR" (proxy=1) */
  1420.         if (command("%s %s", cmd2, local) != PRELIM) {
  1421.             pswitch(0);
  1422.             if (cpend)
  1423.                 abort_remote((FILE *) NULL);
  1424.         }
  1425.         pswitch(1);
  1426.         if (ptabflg)
  1427.             code = -1;
  1428.         (void) signal(SIGINT, oldintr);
  1429.         return;
  1430.     }
  1431.     if (cpend)
  1432.         abort_remote((FILE *) NULL);
  1433.     pswitch(!proxy);
  1434.     if (!cpend && !secndflag) {  /* only if cmd = "RETR" (proxy=1) */
  1435.         if (command("%s %s", cmd2, local) != PRELIM) {
  1436.             pswitch(0);
  1437.             if (cpend)
  1438.                 abort_remote((FILE *) NULL);
  1439.             pswitch(1);
  1440.             if (ptabflg)
  1441.                 code = -1;
  1442.             (void) signal(SIGINT, oldintr);
  1443.             return;
  1444.         }
  1445.     }
  1446.     if (cpend)
  1447.         abort_remote((FILE *) NULL);
  1448.     pswitch(!proxy);
  1449.     if (cpend) {
  1450.         FD_ZERO(&mask);
  1451.         FD_SET(fileno(cin), &mask);
  1452.         if ((nfnd = empty(&mask, 10)) <= 0) {
  1453.             if (nfnd < 0) {
  1454.                 perror("abort");
  1455.             }
  1456.             if (ptabflg)
  1457.                 code = -1;
  1458.             lostpeer(0);
  1459.         }
  1460.         (void) getreply(0);
  1461.         (void) getreply(0);
  1462.     }
  1463.     if (proxy)
  1464.         pswitch(0);
  1465.     pswitch(1);
  1466.     if (ptabflg)
  1467.         code = -1;
  1468.     (void) signal(SIGINT, oldintr);
  1469. }
  1470.  
  1471. void
  1472. reset(void)
  1473. {
  1474.     fd_set mask;
  1475.     int nfnd = 1;
  1476.  
  1477.     FD_ZERO(&mask);
  1478.     while (nfnd > 0) {
  1479.         FD_SET(fileno(cin), &mask);
  1480.         if ((nfnd = empty(&mask,0)) < 0) {
  1481.             perror("reset");
  1482.             code = -1;
  1483.             lostpeer(0);
  1484.         }
  1485.         else if (nfnd) {
  1486.             (void) getreply(0);
  1487.         }
  1488.     }
  1489. }
  1490.  
  1491. char *
  1492. gunique(char *local)
  1493. {
  1494.     static char new[MAXPATHLEN];
  1495.     char *cp = rindex(local, '/');
  1496.     int d, count=0;
  1497.     char ext = '1';
  1498.  
  1499.     if (cp)
  1500.         *cp = '\0';
  1501.     d = access(cp ? local : ".", 2);
  1502.     if (cp)
  1503.         *cp = '/';
  1504.     if (d < 0) {
  1505.         fprintf(stderr, "local: %s: %s\n", local, strerror(errno));
  1506.         return((char *) 0);
  1507.     }
  1508.     (void) strcpy(new, local);
  1509.     cp = new + strlen(new);
  1510.     *cp++ = '.';
  1511.     while (!d) {
  1512.         if (++count == 100) {
  1513.             printf("runique: can't find unique file name.\n");
  1514.             return((char *) 0);
  1515.         }
  1516.         *cp++ = ext;
  1517.         *cp = '\0';
  1518.         if (ext == '9')
  1519.             ext = '0';
  1520.         else
  1521.             ext++;
  1522.         if ((d = access(new, 0)) < 0)
  1523.             break;
  1524.         if (ext != '0')
  1525.             cp--;
  1526.         else if (*(cp - 2) == '.')
  1527.             *(cp - 1) = '1';
  1528.         else {
  1529.             *(cp - 2) = *(cp - 2) + 1;
  1530.             cp--;
  1531.         }
  1532.     }
  1533.     return(new);
  1534. }
  1535.  
  1536. static void
  1537. abort_remote(FILE *din)
  1538. {
  1539.     char buf[BUFSIZ];
  1540.     int nfnd;
  1541.     fd_set mask;
  1542.  
  1543.     /*
  1544.      * send IAC in urgent mode instead of DM because 4.3BSD places oob mark
  1545.      * after urgent byte rather than before as is protocol now
  1546.      */
  1547.     sprintf(buf, "%c%c%c", IAC, IP, IAC);
  1548.     if (send(fileno(cout), buf, 3, MSG_OOB) != 3)
  1549.         perror("abort");
  1550.     fprintf(cout,"%cABOR\r\n", DM);
  1551.     (void) fflush(cout);
  1552.     FD_ZERO(&mask);
  1553.     FD_SET(fileno(cin), &mask);
  1554.     if (din) { 
  1555.         FD_SET(fileno(din), &mask);
  1556.     }
  1557.     if ((nfnd = empty(&mask, 10)) <= 0) {
  1558.         if (nfnd < 0) {
  1559.             perror("abort");
  1560.         }
  1561.         if (ptabflg)
  1562.             code = -1;
  1563.         lostpeer(0);
  1564.     }
  1565.     if (din && FD_ISSET(fileno(din), &mask)) {
  1566.         while (read(fileno(din), buf, BUFSIZ) > 0)
  1567.             /* LOOP */;
  1568.     }
  1569.     if (getreply(0) == ERROR && code == 552) {
  1570.         /* 552 needed for nic style abort */
  1571.         (void) getreply(0);
  1572.     }
  1573.     (void) getreply(0);
  1574. }
  1575.